Trucs et astuces en R

R

Trucs et astuces en R.

Auteur·rice·s
Affiliations

Nassab ABDALLAH

Damien EUZENAT

Date de publication

30 avril 2025

Voici quelques trucs et astuces utiles à connaître sur R, issus en partie des livres The R Inferno et Advanced R, à consulter pour plus de détails.

1 Le fonctionnement du langage R

1.1 Les types d’objet

1.1.1 Généralités

# En savoir plus sur ses données
data("cars")
typeof(cars)
[1] "list"
class(cars)
[1] "data.frame"
mode(cars)
[1] "list"
str(cars)
'data.frame':   50 obs. of  2 variables:
 $ speed: num  4 4 7 7 8 9 10 10 10 11 ...
 $ dist : num  2 10 4 22 16 10 18 26 34 17 ...
dim(cars)
[1] 50  2
c(is.data.frame(cars), is.list(cars), is.vector(cars), is.array(cars))
[1]  TRUE  TRUE FALSE FALSE

La notation L permet d’imposer à R de créer un nombre sous format integer, moins gourmand en mémoire (pour des raisons d’efficacité).

class(1)
[1] "numeric"
class(1L)
[1] "integer"

1.1.2 Les listes

# Créer une liste
liste <- list()

# Pré-allouer une liste de 3 éléments
liste <- vector(mode = "list", 3)
liste
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL
# Ajouter un élément à une liste
liste <- list(1, 2)
# Il faut passer par cette syntaxe
liste <- c(liste, list(3))
liste
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3
# Trier une liste
liste <- list("2" = 2, "0" = 0, "1" = 1)
liste
$`2`
[1] 2

$`0`
[1] 0

$`1`
[1] 1
liste[order(names(liste))]
$`0`
[1] 0

$`1`
[1] 1

$`2`
[1] 2
# Extraction de listes
liste <- list(nombres = 1:5, lettres = letters[1:5])
liste$nombres
[1] 1 2 3 4 5
# On veut faire appel à un élement de la liste à partir d'une variable extérieure
var <- "nombres"
# Ne marche pas, car nombres est en caractère
liste$var
NULL
# Fonctionne
liste[[var]]
[1] 1 2 3 4 5
# Sélection dans une liste
liste <- list(nombres = 1:5, lettres = letters[1:5])
liste["nombres"]
$nombres
[1] 1 2 3 4 5
is.list(liste["nombres"])
[1] TRUE
liste[["nombres"]]
[1] 1 2 3 4 5
is.list(liste[["nombres"]])
[1] FALSE
# Suppression des éléments d'une liste
liste <- list(nombres = 1:5, lettres = letters[1:5])
liste[-1]
$lettres
[1] "a" "b" "c" "d" "e"
liste["nombres"] <- NULL
liste
$lettres
[1] "a" "b" "c" "d" "e"
# Dernier élément de chaque composante d'une liste
liste <- list(1:26, letters)
lapply(liste, tail, 1)
[[1]]
[1] 26

[[2]]
[1] "z"

1.2 Les affectations

1.2.1 Généralités

# Importance des espaces
x<-3
# S'agit-il de ?
x <- 3
# Ou de ?
x < -3
[1] FALSE
# Il s'agit du premier cas !
x
[1] 3
# Les {} permettent de réaliser une affectation (<-) au sein d'un traitement plus complexe !
# Exemple ici : sommer les positions paires multipliées par 2 et les positions impaires multipliées par 3
sum({x <- 1:6 ; x[1:length(x) %% 2 == 0] <- x[1:length(x) %% 2 == 0] * 2 ; x[1:length(x) %% 2 != 0] <- x[1:length(x) %% 2 != 0] * 3 ; x})
[1] 51
# Afficher ou non la valeur de l'objet affecté pendant l'affectation
x <- pi
(x <- pi)
[1] 3.141593

1.2.2 Le comportement de l’opérateur c()

# c() est instable : c(x, y) n'est pas forcément du même type que c(y, x)
# format double
c(NA, Sys.Date())
[1]    NA 20208
# format Date
c(Sys.Date(), NA)
[1] "2025-04-30" NA          
# Combiner des dates et date-times avec c() conduit à des résultats potentiellement incorrects
date <- as.Date("2025-01-01")
datetime <- as.POSIXct("2025-01-01 09:00")
# Correct
c(date, datetime)
[1] "2025-01-01" "2025-01-01"
# Incorrect
c(datetime, date)
[1] "2025-01-01 09:00:00 UTC" "2025-01-01 00:00:00 UTC"
# Valeurs manquantes
# Si le NA est placé avant, c() supprime tous les attributs
# Exemple 1
c(as.Date("2025-01-01"), NA)
[1] "2025-01-01" NA          
c(NA, as.Date("2025-01-01"))
[1]    NA 20089
# Exemple 2
c(NA, as.POSIXct("2025-01-01 09:00"))
[1]         NA 1735722000
c(as.POSIXct("2025-01-01 09:00"), NA)
[1] "2025-01-01 09:00:00 UTC" NA                       
# c() convertit de character > complex > double > integer > logical
c(FALSE, 1L, 2.5)
[1] 0.0 1.0 2.5
c(FALSE, "x")
[1] "FALSE" "x"    
# Combiner 2 facteurs donne un integer
c(factor("a"), factor("b"))
[1] a b
Levels: a b
# Data frames
# c() combines 2 data.frames dans une liste
df1 <- data.frame(x = 1)
df2 <- data.frame(x = 2)
str(c(df1, df1))
List of 2
 $ x: num 1
 $ x: num 1

1.3 Les comparaisons

# Comparaisons multiples
x <- 0.5
# Correct
0 < x & x < 1
# Incorrect
0 < x < 1
Error: <text>:6:7: unexpected '<'
5: # Incorrect
6: 0 < x <
         ^
# Opérations mathématiques
# Infini
1/0
[1] Inf
# Nan = not a number
0/0
[1] NaN
log(-1)
[1] NaN

1.4 Opérateurs de contrôle

# Conditions if / else
x <- 1
# Correct
if (identical(x, 1)) {
print("x est égal à 1")
} else {
print("x est différent de 1")
}
[1] "x est égal à 1"
# Correct
if (identical(x, 1)) {print("x est égal à 1")
} else {print("x est différent de 1")}
[1] "x est égal à 1"
# Correct
if (identical(x, 1)) print("x est égal à 1") else
print("x est différent de 1")
[1] "x est égal à 1"
# Correct
if (identical(x, 1)) print("x est égal à 1") else print("x est différent de 1")
[1] "x est égal à 1"
# Incorrect
if (identical(x, 1)) print("x est égal à 1")
else print("x est différent de 1")
Error: <text>:3:1: unexpected 'else'
2: if (identical(x, 1)) print("x est égal à 1")
3: else
   ^
# Switch
# Fonctions et conditions if / else
condition <- function(langue = "Français") {
if (langue == "Français") {
  "salut"
} else if (langue == "Anglais") {
  "hello"
} else if (langue == "Russe") {
  "привет"
} else {
  stop("salut")
}
}
condition("Anglais")
[1] "hello"
# Autre possibilité avec switch, mais à réserver aux variables caractères !
condition <- function(langue = "Français") {
switch(langue,
       Français = "salut",
       Anglais = "hello",
       Russe = "привет",
       stop("salut")
)
}
condition("Français")
[1] "salut"

1.5 Les valeurs manquantes

# Transformer les valeurs manquantes en 0
x <- data.frame(X1 = c(1, NA, 2), X2 = c(NA, NA, 3))
x
  X1 X2
1  1 NA
2 NA NA
3  2  3
x[is.na(x)] <- 0
x
  X1 X2
1  1  0
2  0  0
3  2  3
# Pour les valeurs manquantes, toujours utiliser is.na et non ==
NA == c(3, 1, 3, NA)
[1] NA NA NA NA
is.na(c(3, 1, 3, NA))
[1] FALSE FALSE FALSE  TRUE
# Utiliser %in% et non == pour vérifier une appartenance à plusieurs variables
x1 <- 1:6
x1 == c(1, 5)
[1]  TRUE FALSE FALSE FALSE FALSE FALSE
x1 %in% c(1, 5)
[1]  TRUE FALSE FALSE FALSE  TRUE FALSE
# Sélection de données en cas de valeurs manquantes
xna <- c(1, NA, 3, 2, 4, 2)
# Avec ce code, les NA sont conservés
xna[xna == 2]
[1] NA  2  2
# Code sans les NA
xna[!is.na(xna) & xna == 2]
[1] 2 2
# Code compact sans les NA
xna[which(xna == 2)]
[1] 2 2
# Incidence des NA dans le calcul de statistiques !
# Besoin de l'instruction na.rm = TRUE pour en supprimer l'incidence
x <- c(1, 5, 6, NA, 8)
mean(x)
[1] NA
mean(x, na.rm = TRUE)
[1] 5
max(x)
[1] NA
max(x, na.rm = TRUE)
[1] 8
# Une moyenne de NA donne NaN (Not a Number) avec na.rm = TRUE !
mean(c(NA, NA, NA), na.rm = TRUE)
[1] NaN
# Et donne NA avec na.rm = FALSE !
mean(c(NA, NA, NA), na.rm = FALSE)
[1] NA

1.6 Sélection d’éléments

# Le 1er élément est numéroté 1 et non 0 comme dans Python
x <- 1:3
x[c(0, 4)] <- c(-1, 9)
# Marche !!
for (i in 0:3) print(x[i])
numeric(0)
[1] 1
[1] 2
[1] 3
# Cas où les noms ne sont pas uniques
x <- c(a = 1, b = 2, a = 3)
x["a"]
a 
1 
x[names(x) %in% "a"]
a a 
1 3 
# Options drop = FALSE
x <- data.frame(X1 = c(1,2), X2 = c(3,4), x3 = c(5,6))
is.data.frame(x[, c(1,2)])
[1] TRUE
is.data.frame(x[, c(1)])
[1] FALSE
is.data.frame(x[, c(1), drop = FALSE])
[1] TRUE
# Fonction subset
x <- data.frame(x1 = c(1,2), x2 = c(3,4), x3 = c(5,6))
subset(x, select = x1)
  x1
1  1
2  2
subset(x, select = -x1)
  x2 x3
1  3  5
2  4  6
# Correct
subset(x, x1 == 1)
  x1 x2 x3
1  1  3  5
# Incorrect
subset(x, x1 = 1)
  x1 x2 x3
1  1  3  5
2  2  4  6
# Référence à des noms de colonne non usuels
df <- data.frame(x = rnorm(5), y = runif(5))
names(df) <- 1:2

# Correct
df$`1`

# Incorrect
df$1
Error: <text>:9:4: unexpected numeric constant
8: # Incorrect
9: df$1
      ^
# Utilisation de assign pour assigner une valeur à un objet en le désignant sous forme caractère
assign('objet', 3:5)
objet
[1] 3 4 5
for (i in 1:5) assign(paste('objet', i, sep = '_'), i)
objet_5
[1] 5

2 Les grandes caractéristiques du langage R

2.1 Principe de vectorisation

Une fonction vectorisée s’applique à tous les éléments du vecteur !!

# Exemple de vecteur
valeurs <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
valeurs <- 1:10
# Valeurs au carré
valeurs ** 2
 [1]   1   4   9  16  25  36  49  64  81 100
# logarithme des valeurs
log(valeurs)
 [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101
 [8] 2.0794415 2.1972246 2.3025851
# Maximum des valeurs
max(valeurs)
[1] 10
# Limite des valeurs
range(valeurs)
[1]  1 10
# Correct
mean(valeurs)
[1] 5.5
# Correct
mean(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
[1] 5.5
# Inattendu
mean(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
[1] 1
# Attention aux parenthèses !
n <- 10
# Inattendu ! Correspond à (1-1, 2-1, 3-1, ..., 10-1)
1:n-1
 [1] 0 1 2 3 4 5 6 7 8 9
# Correct
1:(n-1)
[1] 1 2 3 4 5 6 7 8 9
# Minimum ou maximum élément par élément
x1 <- c(1, 2, 5, 6, 8)
x2 <- c(4, 0, 7, 2, 1)
# Minimum : 2 possibilités
pmin(x1, x2)
[1] 1 0 5 2 1
mapply(min, x1, x2)
[1] 1 0 5 2 1
# Maximum : 2 possibilités
pmax(x1, x2)
[1] 4 2 7 6 8
mapply(max, x1, x2)
[1] 4 2 7 6 8
# Calculer (x - min) / (max - min) pour chaque élément x d'un vecteur
x <- c(1,2,3)
sapply(x, function(xi, mn, mx) {(xi - mn) / (mx - mn)}, mn = min(x), mx = max(x))
[1] 0.0 0.5 1.0

2.2 Principe de coercion

Dans les comparaisons, les objets R sont successivement convertis en logical, integer, numeric, complex et character, jusqu’à ce que la comparaison puisse se faire.

# TRUE / FALSE est transformé en integer (1 / 0)
TRUE == 1
[1] TRUE
TRUE == 2
[1] FALSE
FALSE == 0
[1] TRUE
# TRUE est convertit en character
TRUE == "1"
[1] FALSE
# 5 est convertit en character
5 < '7'
[1] TRUE
# 50 est convertit en character
50 < '7'
[1] TRUE

2.3 Principe de recycling

En R Base, quand 2 vecteurs ne sont pas de même taille, le plus court vecteur est recyclé pour être de même taille que le plus long vecteur.

# Si la taille du plus long vecteur est un entier multiple de la taile du plus court, R n'affiche pas d'avertissement
x <- c(1, 2, 3)
y <- c(1, 2, 3, 4, 5, 6)
x + y
[1] 2 4 6 5 7 9
# Si la taille du plus long vecteur n'est pas un entier multiple de la taille du plus court, R affiche un avertissement
x <- c(1, 2, 3)
y <- c(1, 2, 3, 4, 5, 6, 7)
x + y
Warning in x + y: longer object length is not a multiple of shorter object
length
[1] 2 4 6 5 7 9 8
# Mais certaines fonctions pratiquent le recycling sans avertissement
paste(1:3, 1:2)
[1] "1 1" "2 2" "3 1"
ifelse(1:3, 1:2, 1:2)
[1] 1 2 1
# Et data.frame() renvoie une erreur
#data.frame(1:2, 1:3)

3 Le saviez-vous ?

3.1 Effets des calculs en virgule flottante

sqrt(2) ^ 2 == 2
[1] FALSE
1 / 49 * 49 == 1
[1] FALSE
.1 == .3 / 3
[1] FALSE
seq(0, 1, by=.1) == .3
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
unique(c(.3, .4 - .1, .5 - .2, .6 - .3, .7 - .4))
[1] 0.3 0.3 0.3

3.2 Obtenir de l’informations sur R

# Informations sur la session de R
sessionInfo()
Sys.info()
.Platform

# Version de R
R.version.string
getRversion()

# Lien vers le bureau de l'utilisateur
file.path(Sys.getenv("USERPROFILE"), "Desktop")

# Chemin de l'exécutable R est-il installé ?
R.home("bin")

# Où sont installés les packages R
.libPaths()

# Version d'un package installé (ici openxlsx)
# packageVersion("openxlsx")

3.3 Le pipe sur R

Cet opérateur permet d’enchaîner les opérations et d’avoir un code plus lisible.

Il existe différents types :

  • Le pipe de Rbase : |>

  • Le pipe du tidyverse : %>%

Les deux pipes fonctionnent de la même manière mais diffèrent sur les points suivants :

Thème |> %>%
Placeholder (pour indiquer où placer l’objet)

_

x |> f(y, a = _)

.

x %>% f(y, a = .)

Package Aucun : directement sur R Magrittr (pipe disponible lorsqu’on effectue library(tidyverse)) |
Fonction Impossible Possible
Temps de calcul Rapide Plus lent
Opérateurs |> %>% %<>% %$% %!>% %T>%

Source :

3.4 Conseils divers

Le format en résultat de sapply est imprévisible :

# integer
sapply(1L, function(x) c(x, x))
     [,1]
[1,]    1
[2,]    1
# list
sapply(integer(), function(x) c(x, x))
list()

Le résultat de ifelse() dépend du format de la condition :

# logical
ifelse(NA, 1L, 1L)
[1] NA
# integer
ifelse(FALSE, 1L, 1L)
[1] 1

La fonction if utilisée sans else renvoie NULL si la condition est FALSE. Ceci permet d’écrire de façon élégante des conditions simples. Par exemple, prendre en compte un s final à un nom seulement si la valeur est strictement supérieure à 1 :

NombreDeLignes <- function(baseDeDonnees) {
  ligne <- nrow(baseDeDonnees)
  paste0(ligne, " ligne", if (ligne > 1) "s")
}
NombreDeLignes(mtcars)
[1] "32 lignes"
NombreDeLignes(mtcars[1,])
[1] "1 ligne"

Pré-allouer un vecteur de dimension 3 :

x <- rep(NA, 3)

3.5 List-comprehensions en R

Equivalent des list-comprehensions de Python en R !

# Equivalent des list-comprehensions de Python en R
# Somme des entiers de 1 à 1 000 multiples de 3 ou 5, en une ligne !
# 4 manières de faire
sum({l <- 1:1000 ; l[l %% 3 == 0 | l %% 5 == 0]})
[1] 234168
sum({l <- 1:1000 ; l[seq_along(l) %% 3 == 0 | seq_along(l) %% 5 == 0]})
[1] 234168
sum(l<-(1:1000)[l %% 3 == 0 | l %% 5 == 0])
[1] 234168
sum((1:1000)[(1:1000 %% 3) == 0 | (1:1000 %% 5) == 0])
[1] 234168

4 Fonctions utiles

4.1 Ramasse-miettes (Garbage Collector)

Si la mémoire vive de l’ordinateur est saturée, on peut essayer de la “purger” en utilisant la fonction gc() de R.

gc()
          used (Mb) gc trigger (Mb) max used (Mb)
Ncells  909369 48.6    1779524 95.1  1779524 95.1
Vcells 1768114 13.5   10146329 77.5  7610193 58.1

4.2 La fonction subset()

La fonction subset() présente deux intérêts par rapport à la sélection avec [ :

  • les lignes où la condition évaluée est NA sont retirées :
exemple_subset <- data.frame(x = c(1, 2, NA), y = c("a", "b", "c"))
# Avec []
exemple_subset[exemple_subset$x == 1, ]
    x    y
1   1    a
NA NA <NA>
# Avec subset()
subset(exemple_subset, x == 1)
  x y
1 1 a
  • l’option par défaut est drop = FALSE, ce qui garantit que la base de résultat est un dataframe :
library(tidyverse)
exemple_subset <- data.frame(x = c(1, 2, NA), y = c("a", "b", "c"))
# Avec []
exemple_subset[exemple_subset$x == 1, "x"] %>% is.data.frame()
[1] FALSE
# Avec subset()
subset(exemple_subset, x == 1, x) %>% is.data.frame()
[1] TRUE

4.3 Les fonctions try() et tryCatch()

La fonction try() permet de poursuivre le programme malgré la survenue d’une erreur. Dans l’exemple suivant, le programme affiche bien “Suite du programme” malgré l’erreur au code précédent.

try(log("x")) ; print("Suite du programme")
Error in log("x") : non-numeric argument to mathematical function
[1] "Suite du programme"

La fonction tryCatch() est plus élaborée, et permet de programmer une valeur par défaut en cas d’erreur.

FonctionLog <- function(x) {
  tryCatch(
    error = function(cnd) NA,
    log(x)
  )
}

La fonction renvoie un NA si la fonction log() ne peut pas être appliquée, comme c’est le cas sur l’exemple pour la valeur “a”.

FonctionLog(1)
[1] 0
FonctionLog("x")
[1] NA

4.4 Les fonctions sort(), order() et rank()

sort() trie un vecteur par ordre croissant. rank() donne le rang de chaque élément du vecteur, le plus petit élément se voyant attribué le rang 1. order() renvoie l’indice du vecteur trié par ordre croissant.

vecteur <- c(5,3,1,2,4)
sort(vecteur)
[1] 1 2 3 4 5
order(vecteur)
[1] 3 4 2 5 1
rank(vecteur)
[1] 5 3 1 2 4

Une autre solution que sort() pour trier un vecteur est :

vecteur <- c(5,3,1,2,4)
vecteur[order(vecteur)]
[1] 1 2 3 4 5

À noter aussi que sort() permet aussi d’exécuter simultanément les fonctions sort() et order(). Ainsi :

vecteur <- c(5,3,1,2,4)
sort(vecteur, index.return = TRUE)
$x
[1] 1 2 3 4 5

$ix
[1] 3 4 2 5 1
# Fonction sort()
sort(vecteur, index.return = TRUE)$x
[1] 1 2 3 4 5
sort(vecteur)
[1] 1 2 3 4 5
# Fonction order()
sort(vecteur, index.return = TRUE)$ix
[1] 3 4 2 5 1
order(vecteur)
[1] 3 4 2 5 1

4.5 Les fonctions :, seq(), seq_len() et seq_along()

# Ne pas confondre !
seq(0:10)
 [1]  1  2  3  4  5  6  7  8  9 10 11
0:10
 [1]  0  1  2  3  4  5  6  7  8  9 10
seq(0, 10)
 [1]  0  1  2  3  4  5  6  7  8  9 10
# Privilégier seq_len à : lorsqu'il y a un risque de 0
# Fonctionnement identique
n <- 5
1:n
[1] 1 2 3 4 5
seq_len(n)
[1] 1 2 3 4 5
# Problème avec les 0
n <- 0
1:n
[1] 1 0
seq_len(n)
integer(0)
# Préférer seq_along à : au cas où la taille de l'objet est 0
x <- c() ;length(x)
[1] 0
for (i in 1:length(x)) print(i)
[1] 1
[1] 0
for (i in seq_along(x)) print(i)
for (i in seq(along=x)) print(i)
# Différences seq, seq_len et seq_along

# seq : créé une séquence d'éléments successifs, espacés éventuellement d'un pas
seq(from = 1, to = 10, by = 2)
[1] 1 3 5 7 9
seq(1, 10, 2)
[1] 1 3 5 7 9
# seq_len : créé une séquence d'éléments de 1 jusqu'au paramètre de la fonction (supposé positif)
seq_len(10)
 [1]  1  2  3  4  5  6  7  8  9 10
# seq_along : créé une séquence d'éléments de 1 jusqu'au nombre d'éléments du vecteur
seq_along(c(7,9,1,0))
[1] 1 2 3 4
# seq se comporte comme seq_along si le vecteur comprend plusieurs éléments, et comme seq_len s'il comprend un seul élément

# Plusieurs éléments
vecteur <- c(10, 20, 30)
seq_along(vecteur)
[1] 1 2 3
seq_len(vecteur)
 [1]  1  2  3  4  5  6  7  8  9 10
seq(vecteur)
[1] 1 2 3
# Un seul élement
vecteur <- 10
seq_along(vecteur)
[1] 1
seq_len(vecteur)
 [1]  1  2  3  4  5  6  7  8  9 10
seq(vecteur)
 [1]  1  2  3  4  5  6  7  8  9 10

4.6 Fonction pour copier des données R dans le presse-papier et les coller (par exemple dans Excel)

Pour coller des données de R dans Excel, on peut :

  • faire passer la fonction R CopierColler() proposée ci-dessous sur les données R que l’on souhaite copier dans Excel ;
  • puis coller le presse-papier directement dans Excel.

La fonction peut être assez pratique.

# Copier des données dans le presse-papier
x <- mtcars
CopierColler <- function(x, row.names = FALSE, col.names = TRUE, dec = ",", na = "", sep = "\t", quote = FALSE, ...) {
  write.table(x, "clipboard", sep = sep, row.names = row.names, col.names = col.names, dec = dec, na = na, quote = quote, ...)
}
# Fonctionne sous système Windows, pas Linux
#CopierColler(x)

4.7 Fonctions diverses

browseURL() lance une page Internet.

Outils de débogage :

# Outils de debogage
options(error = recover)
options(error=NULL)

Fonction dput()

# Créer un objet sous forme de code R !
data("mtcars")
dput(mtcars)
structure(list(mpg = c(21, 21, 22.8, 21.4, 18.7, 18.1, 14.3, 
24.4, 22.8, 19.2, 17.8, 16.4, 17.3, 15.2, 10.4, 10.4, 14.7, 32.4, 
30.4, 33.9, 21.5, 15.5, 15.2, 13.3, 19.2, 27.3, 26, 30.4, 15.8, 
19.7, 15, 21.4), cyl = c(6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 
8, 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 4, 4, 4, 8, 6, 8, 4), 
    disp = c(160, 160, 108, 258, 360, 225, 360, 146.7, 140.8, 
    167.6, 167.6, 275.8, 275.8, 275.8, 472, 460, 440, 78.7, 75.7, 
    71.1, 120.1, 318, 304, 350, 400, 79, 120.3, 95.1, 351, 145, 
    301, 121), hp = c(110, 110, 93, 110, 175, 105, 245, 62, 95, 
    123, 123, 180, 180, 180, 205, 215, 230, 66, 52, 65, 97, 150, 
    150, 245, 175, 66, 91, 113, 264, 175, 335, 109), drat = c(3.9, 
    3.9, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92, 
    3.07, 3.07, 3.07, 2.93, 3, 3.23, 4.08, 4.93, 4.22, 3.7, 2.76, 
    3.15, 3.73, 3.08, 4.08, 4.43, 3.77, 4.22, 3.62, 3.54, 4.11
    ), wt = c(2.62, 2.875, 2.32, 3.215, 3.44, 3.46, 3.57, 3.19, 
    3.15, 3.44, 3.44, 4.07, 3.73, 3.78, 5.25, 5.424, 5.345, 2.2, 
    1.615, 1.835, 2.465, 3.52, 3.435, 3.84, 3.845, 1.935, 2.14, 
    1.513, 3.17, 2.77, 3.57, 2.78), qsec = c(16.46, 17.02, 18.61, 
    19.44, 17.02, 20.22, 15.84, 20, 22.9, 18.3, 18.9, 17.4, 17.6, 
    18, 17.98, 17.82, 17.42, 19.47, 18.52, 19.9, 20.01, 16.87, 
    17.3, 15.41, 17.05, 18.9, 16.7, 16.9, 14.5, 15.5, 14.6, 18.6
    ), vs = c(0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 
    0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1), am = c(1, 
    1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 
    0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1), gear = c(4, 4, 4, 3, 
    3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 
    3, 3, 4, 5, 5, 5, 5, 5, 4), carb = c(4, 4, 1, 1, 2, 1, 4, 
    2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2, 2, 4, 2, 1, 
    2, 2, 4, 6, 8, 2)), row.names = c("Mazda RX4", "Mazda RX4 Wag", 
"Datsun 710", "Hornet 4 Drive", "Hornet Sportabout", "Valiant", 
"Duster 360", "Merc 240D", "Merc 230", "Merc 280", "Merc 280C", 
"Merc 450SE", "Merc 450SL", "Merc 450SLC", "Cadillac Fleetwood", 
"Lincoln Continental", "Chrysler Imperial", "Fiat 128", "Honda Civic", 
"Toyota Corolla", "Toyota Corona", "Dodge Challenger", "AMC Javelin", 
"Camaro Z28", "Pontiac Firebird", "Fiat X1-9", "Porsche 914-2", 
"Lotus Europa", "Ford Pantera L", "Ferrari Dino", "Maserati Bora", 
"Volvo 142E"), class = "data.frame")

Fonction tribble()

# En tidyverse, la fonction tribble peut être utile pour créer des bases lignes par lignes
library(tidyverse)
tribble(
  ~x, ~y,
  "a",   1,
  "b",   2
)
# A tibble: 2 × 2
  x         y
  <chr> <dbl>
1 a         1
2 b         2
# Définir ses propres opérateurs
# R reconnait le texte entre %% comme un opérateur binaire
# Exemple, simplifier la fonction paste
'%+%' <- function(x, y) { paste(x, y, sep = "") }
"Groupe_" %+% 0:9
 [1] "Groupe_0" "Groupe_1" "Groupe_2" "Groupe_3" "Groupe_4" "Groupe_5"
 [7] "Groupe_6" "Groupe_7" "Groupe_8" "Groupe_9"
# Récupérer les éléments à la diagonale d'un dataframe
diag(as.matrix(mtcars))
 [1]  21.00   6.00 108.00 110.00   3.15   3.46  15.84   1.00   0.00   4.00
[11]   4.00
# S'assurer qu'un objet R existe déjà
exists("mtcars")
[1] TRUE
# Penser au print
for (i in 1:5) i
for (i in 1:5) print(i)
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
# Différences print et cat
cat("Salut !\nComment vas-tu ?")
Salut !
Comment vas-tu ?
print("Salut !\nComment vas-tu ?")
[1] "Salut !\nComment vas-tu ?"

4.8 Quelques fonctions mathématiques

integrate() calcule l’aire sous la courbe \(f()\).

integrate(sin, 0, pi / 2)
1 with absolute error < 1.1e-14

uniroot() trouve la valeur de \(x\) telle que \(f(x) = 0\).

uniroot(function(x) x ** 3, c(-1, 1))
$root
[1] 0

$f.root
[1] 0

$iter
[1] 1

$init.it
[1] NA

$estim.prec
[1] 1

optimise() trouve le maximum ou le minimum d’une fonction sur un intervalle donné.

optimise(function(x) -x ** 2, c(-1, 1), maximum = TRUE)
$maximum
[1] -2.775558e-17

$objective
[1] -7.70372e-34

4.9 Ajouter des guillemets dans une chaîne de caractères

La fonction shQuote() permet d’ajouter des guillemets dans une chaîne de caractères sous Windows.

paste("valeur =", shQuote("10"))
[1] "valeur = '10'"

5 Importer rapidement un fichier R dans SAS

Le format de données SAS étant propriétaire, il n’est pas possible de créer directement en R des bases SAS d’extension .sas7bdat. Une solution relativement rapide pour importer une base R en SAS est de passer par le format intermédiaire .xpt qui conserve les noms et formats des variables.

5.1 Copie de la base R en format xpt

Il faut d’abord copier la base R en format xpt en utilisant la fonction write_xpt() du package haven. Pour que la manipulation proposée ici fonctionne, il faut bien veiller à ce que la version du xpt soit la version 5.

# On copie la base mtcars en format xpt sur le bureau de l'utilisateur
haven::write_xpt(mtcars, file.path(Sys.getenv("USERPROFILE"), "Desktop", "mtcars.xpt"), version = 5)

5.2 Import de la base xpt en SAS

La base R copiée en format xpt peut ensuite être importée en SAS avec le code suivant :

libname xptfile xport "C:\Users\&sysuserid.\Desktop\mtcars.xpt";
proc copy inlib = xptfile outlib = work;
run;

Par défaut, la base est nommée du nom de la base xpt et se trouve dans la work de SAS, mais outlib peut être paramétré avec une autre libname.